<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="期货代码" prop="code">
        <el-input v-model="queryParams.code" placeholder="请输入期货代码" clearable style="width: 200px"
                  @keyup.enter="handleQuery"/>
      </el-form-item>
      <el-form-item label="交易日期" style="width: 308px;">
        <el-date-picker v-model="dateRange" value-format="YYYY-MM-DD" type="daterange" range-separator="-"
                        start-placeholder="开始日期" end-placeholder="结束日期">
        </el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['kylin:futureDailyQuote:add']">
          新增
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate"
                   v-hasPermi="['kylin:futureDailyQuote:edit']">
          修改
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete"
                   v-hasPermi="['kylin:futureDailyQuote:remove']">
          删除
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="warning" plain icon="Download" @click="handleExport"
                   v-hasPermi="['kylin:futureDailyQuote:export']">
          导出
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="info" plain icon="Histogram" @click="showKlineChart">
          K线图
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="primary" plain icon="Download" @click="handleQuoteDownload">
          行情下载
        </el-button>
      </el-col>
      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="futureQuoteList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center"/>
      <el-table-column label="主键" align="center" prop="id" v-if="false"/>
      <el-table-column label="期货代码" align="center" prop="code" width="100" :show-overflow-tooltip="true"/>
      <el-table-column label="交易日期" align="center" prop="date" width="120" :show-overflow-tooltip="true"/>
      <el-table-column label="开盘价" align="center" prop="open" :show-overflow-tooltip="true"/>
      <el-table-column label="最高价" align="center" prop="high" :show-overflow-tooltip="true"/>
      <el-table-column label="最低价" align="center" prop="low" :show-overflow-tooltip="true"/>
      <el-table-column label="收盘价" align="center" prop="close" :show-overflow-tooltip="true"/>
      <el-table-column label="成交量" align="center" prop="volume"/>
      <el-table-column label="持仓量" align="center" prop="hold"/>
      <el-table-column label="结算价" align="center" prop="settle" :show-overflow-tooltip="true"/>
      <el-table-column label="操作" align="center" width="150" class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)"
                     v-hasPermi="['kylin:futureDailyQuote:edit']">修改
          </el-button>
          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"
                     v-hasPermi="['kylin:futureDailyQuote:remove']">删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
                v-model:limit="queryParams.pageSize" @pagination="getList"/>

    <!-- 添加或修改期货日线行情对话框 -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
      <el-form ref="futureQuoteRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="期货代码" prop="code">
          <el-input v-model="form.code" placeholder="请输入期货代码"/>
        </el-form-item>
        <el-form-item label="交易日期" prop="date">
          <el-date-picker v-model="form.date" type="date" placeholder="选择交易日期" value-format="YYYY-MM-DD"/>
        </el-form-item>
        <el-form-item label="开盘价" prop="open">
          <el-input v-model="form.open" type="number" placeholder="请输入开盘价"/>
        </el-form-item>
        <el-form-item label="最高价" prop="high">
          <el-input v-model="form.high" type="number" placeholder="请输入最高价"/>
        </el-form-item>
        <el-form-item label="最低价" prop="low">
          <el-input v-model="form.low" type="number" placeholder="请输入最低价"/>
        </el-form-item>
        <el-form-item label="收盘价" prop="close">
          <el-input v-model="form.close" type="number" placeholder="请输入收盘价"/>
        </el-form-item>
        <el-form-item label="成交量" prop="volume">
          <el-input v-model="form.volume" type="number" placeholder="请输入成交量"/>
        </el-form-item>
        <el-form-item label="持仓量" prop="hold">
          <el-input v-model="form.hold" type="number" placeholder="请输入持仓量"/>
        </el-form-item>
        <el-form-item label="结算价" prop="settle">
          <el-input v-model="form.settle" type="number" placeholder="请输入结算价"/>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- K线图对话框 - 设置为全屏模式 -->
    <el-dialog title="K线图" v-model="klineChartOpen" fullscreen append-to-body>
      <div id="klineChart" style="width: 100%; height: 95vh;"></div>
    </el-dialog>
  </div>
</template>

<script setup name="FutureQuote">
import {
  addFutureQuote,
  delFutureQuote,
  fetchFutureQuote,
  getFutureQuote,
  listFutureQuote,
  updateFutureQuote
} from "@/api/kylin/futureQuote.js";
import {ElMessage} from "element-plus";
import {getCurrentInstance, onMounted, ref, nextTick, watch} from "vue";
import * as echarts from 'echarts';
// 注册组件
// echarts.use([GraphicComponent]);

const {proxy} = getCurrentInstance();

const futureQuoteList = ref([]);
const loading = ref(false);
const total = ref(0);
const open = ref(false);
const title = ref("");
const showSearch = ref(true);
const multiple = ref(true);
const single = ref(true);
const dateRange = ref([]);
const klineChartOpen = ref(false);
const klineChartInstance = ref(null);
const queryParams = ref({
  pageNum: 1,
  pageSize: 10,
  code: undefined,
  beginDate: undefined,
  endDate: undefined
});
const form = ref({
  id: undefined,
  code: undefined,
  date: undefined,
  open: undefined,
  high: undefined,
  low: undefined,
  close: undefined,
  volume: 0,
  hold: 0,
  settle: undefined
});
const rules = ref({
  code: [
    {required: true, message: "期货代码不能为空", trigger: "blur"}
  ],
  date: [
    {required: true, message: "交易日期不能为空", trigger: "blur"}
  ],
  open: [
    {required: true, message: "开盘价不能为空", trigger: "blur"}
  ],
  high: [
    {required: true, message: "最高价不能为空", trigger: "blur"}
  ],
  low: [
    {required: true, message: "最低价不能为空", trigger: "blur"}
  ],
  close: [
    {required: true, message: "收盘价不能为空", trigger: "blur"}
  ]
});
const queryRef = ref(null);
const futureQuoteRef = ref(null);
const ids = ref([]);

/**
 * 初始化查询
 */
const initQuery = () => {
  queryParams.value = {
    pageNum: 1,
    pageSize: 10,
    code: undefined,
    beginDate: undefined,
    endDate: undefined
  };
  dateRange.value = [];
};

/**
 * 获取列表
 */
const getList = async () => {
  loading.value = true;
  try {
    const data = await listFutureQuote(queryParams.value);
    futureQuoteList.value = data.rows;
    total.value = data.total;
    loading.value = false;
  } catch (error) {
    console.error("获取期货日线行情列表失败", error);
    loading.value = false;
  }
};

/**
 * 搜索
 */
const handleQuery = () => {
  queryParams.value.pageNum = 1;
  if (dateRange.value && dateRange.value.length > 0) {
    queryParams.value.beginDate = dateRange.value[0];
    queryParams.value.endDate = dateRange.value[1];
  } else {
    queryParams.value.beginDate = undefined;
    queryParams.value.endDate = undefined;
  }
  getList();
};

/**
 * 重置
 */
const resetQuery = () => {
  if (queryRef.value) {
    queryRef.value.resetFields();
  }
  dateRange.value = [];
  initQuery();
  getList();
};

/**
 * 打开新增对话框
 */
const handleAdd = () => {
  form.value = {
    id: undefined,
    code: undefined,
    date: undefined,
    open: undefined,
    high: undefined,
    low: undefined,
    close: undefined,
    volume: 0,
    hold: 0,
    settle: undefined
  };
  open.value = true;
  title.value = "新增期货日线行情";
};

/**
 * 打开修改对话框
 */
const handleUpdate = async (row) => {
  const id = row.id || row;
  const data = await getFutureQuote(id);
  form.value = data;
  open.value = true;
  title.value = "修改期货日线行情";
};

/**
 * 删除
 */
const handleDelete = async (row) => {
  // 处理批量删除和单行删除的不同情况
  let deleteIds = [];
  
  // 如果传入了row参数，检查是否为行数据对象
  if (row && typeof row === 'object' && !Array.isArray(row) && !('isTrusted' in row)) {
    // 单行删除情况
    const id = row.id || row;
    deleteIds = id instanceof Array ? id : [id];
  } else {
    // 批量删除情况 - 使用已选中的ids
    deleteIds = [...ids.value];
  }
  
  // 检查是否有选中的数据
  if (deleteIds.length === 0) {
    ElMessage.warning("请选择要删除的数据项");
    return;
  }
  
  await proxy.$modal.confirm("是否确认删除选中的数据项？").then(async () => {
    await delFutureQuote(deleteIds.join(",")).then(() => {
      getList();
      ElMessage.success("删除成功");
    });
  });
};

/**
 * 导出
 */
const handleExport = () => {
  proxy.download('/kylin/futureDailyQuote/export', queryParams.value, `future_quote_${new Date().getTime()}.xlsx`);
};

/**
 * 行情下载
 */
const handleQuoteDownload = async () => {
  // 检查期货代码是否已输入
  if (!queryParams.value.code) {
    ElMessage.warning('请先录入需要下载的合约代码');
    // 聚焦到期货代码输入框
    if (queryRef.value && queryRef.value.$el) {
      const inputEl = queryRef.value.$el.querySelector('input');
      if (inputEl) {
        inputEl.focus();
      }
    }
    return;
  }
  
  try {
    loading.value = true;
    ElMessage.info(`正在从外部数据源获取${queryParams.value.code}的行情数据，请稍候...`);
    // 调用后台fetch接口下载行情数据
    const response = await fetchFutureQuote(queryParams.value.code);
    if (response.code === 200) {
      ElMessage.success(response.msg || `成功获取${queryParams.value.code}的行情数据`);
      // 重新获取列表数据以显示最新下载的行情
      getList();
    } else {
      ElMessage.error(response.msg || '获取行情数据失败');
    }
  } catch (error) {
    ElMessage.error('获取行情数据时发生错误');
    console.error('获取行情数据错误:', error);
  } finally {
    loading.value = false;
  }
};

/**
 * 提交表单
 */
const submitForm = async () => {
  try {
    await futureQuoteRef.value.validate();
    if (form.value.id) {
      await updateFutureQuote(form.value);
    } else {
      await addFutureQuote(form.value);
    }
    open.value = false;
    getList();
    ElMessage.success(form.value.id ? "修改成功" : "新增成功");
  } catch (error) {
    console.error("提交表单失败", error);
  }
};

/**
 * 取消
 */
const cancel = () => {
  open.value = false;
  if (futureQuoteRef.value) {
    futureQuoteRef.value.resetFields();
  }
};

/**
 * 多选框选中数据变化
 */
const handleSelectionChange = (selection) => {
  ids.value = selection.map(item => item.id);
  multiple.value = !selection.length;
  single.value = selection.length !== 1;
};

/**
 * 获取所有K线图数据
 */
const getAllKlineData = async () => {
  loading.value = true;
  try {
    // 创建查询参数副本，设置一个较大的pageSize值获取全部数据
    // 避免设置为0导致后端除零错误
    const fullQueryParams = {
      ...queryParams.value,
      pageSize: 10000 // 设置一个足够大的值以获取所有数据
    };

    const data = await listFutureQuote(fullQueryParams);
    loading.value = false;
    return data.rows;
  } catch (error) {
    console.error("获取所有期货日线行情数据失败", error);
    loading.value = false;
    return [];
  }
};

/**
 * 显示K线图
 */
const showKlineChart = async () => {
  // 检查期货代码是否已输入
  if (!queryParams.value.code) {
    ElMessage.warning('请先录入期货代码');
    return;
  }
  
  // 显示加载中
  loading.value = true;

  try {
    // 获取所有满足查询条件的数据
    const allData = await getAllKlineData();

    if (allData.length === 0) {
      ElMessage.warning(`没有可显示的${queryParams.value.code}行情数据`);
      return;
    }

    // 打开对话框
    klineChartOpen.value = true;

    // 等待对话框渲染完成
    await nextTick();

    // 临时存储原始数据
    const originalData = [...futureQuoteList.value];
    // 设置为全部数据用于绘制K线图
    futureQuoteList.value = allData;

    // 初始化K线图
    initKlineChart();

    // 监听对话框关闭，恢复原始数据和销毁图表
    const unwatch = watch(klineChartOpen, (newVal) => {
      if (!newVal) {
        futureQuoteList.value = originalData;
        // 销毁图表实例
        if (klineChartInstance.value) {
          klineChartInstance.value.dispose();
          klineChartInstance.value = null;
        }
        unwatch(); // 取消监听
      }
    });
  } finally {
    loading.value = false;
  }
};

/**
 * 初始化K线图
 */
const initKlineChart = () => {
  // 销毁已存在的图表实例
  if (klineChartInstance.value) {
    klineChartInstance.value.dispose();
  }

  // 创建新的图表实例
  const chartDom = document.getElementById('klineChart');
  if (!chartDom) return;

  klineChartInstance.value = echarts.init(chartDom);

  // 处理数据格式
  const { dates, ohlcData, volumeData } = processKlineData();

  // 基于参考链接简化和规范化的K线图配置
  const option = {
    backgroundColor: '#f9f9f9',
    title: {
      text: `${futureQuoteList.value[0]?.code || '期货'} 行情图`,
      left: 'center',
      top: 20
    },
    tooltip: {
      trigger: 'axis',
      axisPointer: { type: 'cross' },
      formatter: function(params) {
        if (!params || params.length === 0) {
          return "暂无数据";
        }
        
        // 安全获取日期
        const date = params[0]?.axisValue || '';
        let tooltipContent = `<strong>${date}</strong><br/>`;
        
        // 遍历所有数据系列
        params.forEach((item) => {
          if (item.seriesType === 'custom') {
            const ohlcItem = item.data;
            if (ohlcItem && ohlcItem.length >= 4) {
              const open = ohlcItem[0];
              const close = ohlcItem[3];
              const high = ohlcItem[1];
              const low = ohlcItem[2];
              
              // 计算涨跌幅并设置颜色
              const color = close > open ? '#ffb3b3' : '#b3ffb3';
              const changePercent = open !== 0 ? ((close - open) / open * 100).toFixed(2) : '0.00';
              
              tooltipContent += `开盘: ${open.toFixed(2)}<br/>`;
              tooltipContent += `最高: ${high.toFixed(2)}<br/>`;
              tooltipContent += `最低: ${low.toFixed(2)}<br/>`;
              tooltipContent += `收盘: <span style="color: ${color}">${close.toFixed(2)}</span><br/>`;
              tooltipContent += `涨跌幅: <span style="color: ${color}">${changePercent}%</span><br/>`;
            }
          } else if (item.seriesType === 'bar') {
            // 显示成交量信息
            const volume = item.data || 0;
            tooltipContent += `成交量: ${volume.toLocaleString()}<br/>`;
          }
        });
        
        return tooltipContent;
      }
    },
    legend: {
      data: ['OHLC', '成交量'],
      top: 50
    },
    grid: [
      { left: '5%', right: '2%', top: '15%', height: '60%' },
      { left: '5%', right: '2%', top: '78%', height: '15%' }
    ],
    xAxis: [
      {
        type: 'category',
        data: dates,
        scale: true,
        boundaryGap: false,
        axisLine: { onZero: false },
        splitLine: { show: false }
      },
      {
        type: 'category',
        gridIndex: 1,
        data: dates,
        scale: true,
        boundaryGap: false,
        axisLine: { show: false },
        axisTick: { show: false },
        splitLine: { show: false }
      }
    ],
    yAxis: [
      {
        scale: true,
        splitArea: { show: true },
        splitLine: { lineStyle: { type: 'dashed' } }
      },
      {
        scale: true,
        gridIndex: 1,
        splitNumber: 2,
        axisLine: { show: false },
        axisTick: { show: false },
        splitLine: { lineStyle: { type: 'dashed' } }
      }
    ],
    dataZoom: [
      {
        type: 'inside',
        xAxisIndex: [0, 1],
        start: 0,
        end: 100
      },
      {
        show: true,
        xAxisIndex: [0, 1],
        type: 'slider',
        top: '94%',
        start: 0,
        end: 100
      }
    ],
    series: [
      {
        name: 'OHLC',
        type: 'custom',
        data: ohlcData,
        renderItem: function(params, api) {
          // 获取当前数据项的位置和值
          const xValue = api.value(0);
          const open = api.value(1);
          const close = api.value(2);
          const high = api.value(3);
          const low = api.value(4);
          
          // 计算坐标位置
          const xAxisPoint = api.coord([xValue, 0]);
          const openPoint = api.coord([xValue, open]);
          const closePoint = api.coord([xValue, close]);
          const highPoint = api.coord([xValue, high]);
          const lowPoint = api.coord([xValue, low]);
          
          // 计算柱状图的宽度
          const halfWidth = Math.max(1, api.size([1, 0])[0] * 0.4);
          
          // 判断涨跌
          const isIncrease = close >= open;
          const color = isIncrease ? '#ffb3b3' : '#b3ffb3';
          
          // 创建图形元素
          const rectShape = echarts.graphic.clipRectByRect({
            x: xAxisPoint[0] - halfWidth,
            y: Math.min(openPoint[1], closePoint[1]),
            width: halfWidth * 2,
            height: Math.abs(openPoint[1] - closePoint[1])
          }, {
            x: params.coordSys.x,
            y: params.coordSys.y,
            width: params.coordSys.width,
            height: params.coordSys.height
          });
          
          const lineShape = echarts.graphic.clipRectByRect({
            x: xAxisPoint[0] - 0.5,
            y: highPoint[1],
            width: 1,
            height: lowPoint[1] - highPoint[1]
          }, {
            x: params.coordSys.x,
            y: params.coordSys.y,
            width: params.coordSys.width,
            height: params.coordSys.height
          });
          
          // 返回图形元素组
          return rectShape && lineShape ? {
            type: 'group',
            children: [
              {
                type: 'rect',
                shape: rectShape,
                style: {
                  fill: color
                }
              },
              {
                type: 'line',
                shape: {
                  x1: xAxisPoint[0],
                  y1: highPoint[1],
                  x2: xAxisPoint[0],
                  y2: lowPoint[1]
                },
                style: {
                  stroke: color,
                  lineWidth: 1
                }
              }
            ]
          } : null;
        },
        dimensions: ['date', 'open', 'close', 'high', 'low']
      },
      {
        name: '成交量',
        type: 'bar',
        xAxisIndex: 1,
        yAxisIndex: 1,
        data: volumeData,
        itemStyle: {
            color: function(params) {
              const ohlcItem = ohlcData[params.dataIndex];
              if (ohlcItem && ohlcItem.length >= 5) {
                return ohlcItem[2] >= ohlcItem[1] ? '#ffb3b3' : '#b3ffb3';
              }
              return '#808080';
            }
          }
      }
    ]
  };

  klineChartInstance.value.setOption(option);
};

/**
 * 处理K线图数据
 */
const processKlineData = () => {
  // 按日期排序并提取数据
  const sortedData = [...(futureQuoteList.value || [])].sort((a, b) => 
    new Date(a.date) - new Date(b.date)
  );

  const dates = [];
  const ohlcData = [];
  const volumeData = [];

  sortedData.forEach(item => {
    const date = item.date;
    const openPrice = parseFloat(item.open || 0);
    const closePrice = parseFloat(item.close || 0);
    const highPrice = parseFloat(item.high || 0);
    const lowPrice = parseFloat(item.low || 0);
    const volume = parseFloat(item.volume || 0);
    
    dates.push(date);
    
    // 按照OHLC格式整理数据 [date, open, close, high, low]
    ohlcData.push([date, openPrice, closePrice, highPrice, lowPrice]);
    
    // 成交量数据
    volumeData.push(volume);
  });

  return { dates, ohlcData, volumeData };
};

// 监听窗口大小变化，调整图表大小
const handleResize = () => {
  if (klineChartInstance.value) {
    klineChartInstance.value.resize();
  }
};

// 注册事件监听器
onMounted(() => {
  window.addEventListener('resize', handleResize);
});


// 初始化
initQuery();
getList();
</script>